#pragma once

#include <asio.hpp>
#include <functional>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <string>

namespace SeanNetwork {

/**
 * @brief Timer callback function type.
 * @param timerId The ID of the timer that triggered the callback
 */
using TimerCallback = std::function<void(uint32_t)>;

/**
 * 定时器类型枚举
 */
enum class TimerType {
    OneShot,  // 一次性定时器
    Repeated  // 重复定时器
};

/**
 * @brief Timer configuration object.
 */
struct TimerConfig {
    uint32_t InitialDelayMs;  // Initial delay before first trigger
    uint32_t IntervalMs;      // Interval between triggers (0 for one-shot timer)
    bool AutoReset;           // Whether to reset the timer after it fires
    
    TimerConfig(uint32_t initialDelayMs = 0, uint32_t intervalMs = 0, bool autoReset = true)
        : InitialDelayMs(initialDelayMs), IntervalMs(intervalMs), AutoReset(autoReset) {
    }
};

/**
 * @brief Timer manager for scheduling and managing recurring and one-shot timers.
 */
class TimerManager {
public:
    /**
     * @brief Constructs a TimerManager instance.
     * @param ioContext The asio::io_context to use for timers
     */
    TimerManager(asio::io_context& ioContext);
    
    /**
     * @brief Destructor that cancels all active timers.
     */
    ~TimerManager();
    
    /**
     * @brief Creates a timer with the specified configuration.
     * 
     * @param config Timer configuration
     * @param callback Function to call when the timer fires
     * @param name Optional descriptive name for debugging
     * @return Timer ID that can be used to control the timer
     */
    uint32_t CreateTimer(
        const TimerConfig& config,
        TimerCallback callback,
        const std::string& name = "");
    
    /**
     * @brief 添加简易定时器
     * 
     * @param delayMs 延迟/间隔时间（毫秒）
     * @param callback 回调函数
     * @param timerType 定时器类型
     * @param name 定时器名称（可选）
     * @return 定时器ID
     */
    uint32_t AddTimer(
        uint32_t delayMs,
        std::function<void()> callback,
        TimerType timerType = TimerType::OneShot,
        const std::string& name = "");
    
    /**
     * @brief 取消定时器
     * 
     * @param timerId 定时器ID
     * @return 是否成功取消
     */
    bool CancelTimer(uint32_t timerId);
    
    /**
     * @brief 清除所有定时器
     */
    void ClearAllTimers();
    
    /**
     * @brief Starts a timer.
     * 
     * @param timerId The ID of the timer to start
     * @return True if the timer was started, false if not found
     */
    bool StartTimer(uint32_t timerId);
    
    /**
     * @brief Stops a timer.
     * 
     * @param timerId The ID of the timer to stop
     * @return True if the timer was stopped, false if not found
     */
    bool StopTimer(uint32_t timerId);
    
    /**
     * @brief Restarts a timer with its configured delay.
     * 
     * @param timerId The ID of the timer to restart
     * @return True if the timer was restarted, false if not found
     */
    bool RestartTimer(uint32_t timerId);
    
    /**
     * @brief Destroys a timer, removing it from the manager.
     * 
     * @param timerId The ID of the timer to destroy
     * @return True if the timer was destroyed, false if not found
     */
    bool DestroyTimer(uint32_t timerId);
    
    /**
     * @brief Updates the configuration of an existing timer.
     * 
     * @param timerId The ID of the timer to update
     * @param config The new configuration
     * @return True if the timer was updated, false if not found
     */
    bool UpdateTimer(uint32_t timerId, const TimerConfig& config);
    
    /**
     * @brief Checks if a timer is active.
     * 
     * @param timerId The ID of the timer to check
     * @return True if the timer exists and is active
     */
    bool IsTimerActive(uint32_t timerId) const;
    
    /**
     * @brief Gets the configuration of a timer.
     * 
     * @param timerId The ID of the timer
     * @param config Output parameter to receive the configuration
     * @return True if the timer exists and the configuration was copied
     */
    bool GetTimerConfig(uint32_t timerId, TimerConfig& config) const;
    
    /**
     * @brief Gets the name of a timer.
     * 
     * @param timerId The ID of the timer
     * @return The name of the timer, or empty string if not found
     */
    std::string GetTimerName(uint32_t timerId) const;
    
    // 设置定时器
    uint32_t SetTimer(uint32_t intervalMs, std::function<void()> callback, bool repeat = false);
    
    // 更新定时器（需要在主循环中调用）
    void Update(float deltaTime);
    
private:
    struct TimerData {
        uint32_t Id;
        TimerConfig Config;
        TimerCallback Callback;
        std::shared_ptr<asio::steady_timer> Timer;
        bool Active;
        std::string Name;
        
        TimerData()
            : Id(0), Active(false) {
        }
    };
    
    void HandleTimerExpired(uint32_t timerId, const asio::error_code& error);
    
    asio::io_context& m_IoContext;
    asio::strand<asio::io_context::executor_type> m_Strand;
    
    std::unordered_map<uint32_t, TimerData> m_Timers;
    mutable std::mutex m_TimersMutex;
    
    uint32_t m_NextTimerId;
};

} // namespace SeanNetwork
